package com.zebra.register;

import com.zebra.remoting.config.ServerType;
import com.zebra.remoting.connection.Connection;
import com.zebra.remoting.connection.DefaultConnectionFactory;
import com.zebra.remoting.protocol.ZebraCodec;
import lombok.extern.slf4j.Slf4j;

/**
 * 注册中心 最佳环境，都是 处于内网环境； 和TMS 在一起； GW 可以随便部署；
 * 注册中心启动最好是依次启动不要同时启动;
 *
 serverId 用最新

 -------Ratel-集群算法-----------
 目标：
 多台部署，任何一台故障，不影响整个架构稳定性； 任意启动一台可以即可加入集群；
 核心： 以最小serverId 为Leader，免去了推荐算法； 2， leader 和 follower 保持心跳 ， 同时 follower 和 leader 也发心跳；
        follower 向 下届 leader 发消息注册， leader收到消息 成为 leader； leader 向 follower 发 leader信息； follower 启动定时检测任务；
 实现：
 1，启动：
   1.1，启动会自动清理redis 数据； 注册中心则清楚；【清除需要，ping2次校验】
   1.2，先入为主： 当第一个启动时，设置为主；第二个启动时，先根据redis，如果已经 有master 则和master建立连接； 循环 20秒一次；
   1.3，启动是如果redis 中已有注册中心，但是master标志位不是master 则 需要发一个消息给 认为是master的让他成为master；
 2，RA断线处理：
   2.1，当检测到Slave，断开，则master 直接从redis 中移除；
   2.2，当检测到master断开，则从redis中读取出所有RA，依次与之连接；以serverId 最小为master；  发更改master消息；
 3，工作：
   3.1,  发现某个服务器断开则需要发消息给master 判断处理；
 *
 * 二， 监控其他服务：
 * 1， 其他服务器断开，发消息给Master注册中心， 有master决定是否从redis 移除；
 * 2，如果，master故障，先推举出master； 然后再走正常流程；
 */
@Slf4j
public class RegisterClient {

    private DefaultConnectionFactory connectionFactory;

    private static RegisterClient client = new RegisterClient();

    private RegisterClient(){
    }

    public static RegisterClient getInstance(){
        return client;
    }

    public void start(RegisterClientHandler clientHandler){
        connectionFactory = new DefaultConnectionFactory();
        connectionFactory.registerCommandHandler(clientHandler);
        connectionFactory.registerRpcCodec(new ZebraCodec());
        connectionFactory.registerHeartbeatProcessor(new RegisterHeartHandler());
        connectionFactory.init();
    }

    public Connection connection(String ip, int port, int serverId, ServerType severType)throws Exception{
        return connectionFactory.connection(ip, port, serverId, severType, 3000);
    }

}
